/**
 * @constructor
 * @this {BaseMediator}
 */
function BaseMediator()
{
	/** @type {jQuery} */
	this.view = null;
	/** @type {jQuery} */
	this.content = null;
	/** @type {View} */
	this.shell = null;
	/**
	 * Selector for toolbar button
	 * @type {String}
	 */
	this.button = null;
	/** @type {Boolean} */
	this.enabled = true;
	/** @type {Boolean} */
	this.visible = false;
	/** @type {jQuery} */
	this.bar = null;
}

/**
 * @param {String} icon
 * @param {String} title
 * @param {Function(Event)} handler
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.addButton = function(icon, title, handler)
{
	"use strict";

	this.view.find('.buttons')
		.prepend($('<button>')
			.attr('title', title)
			.click(handler)
			.appendIcon(icon, true)
		);

	return this;
};

/**
 * Activate or deactivate busy overlay
 * @param {Boolean} [busy = true]
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.busy = function(busy)
{
	"use strict";

	if (busy === undefined) { busy = true; }

	if (busy)
	{
		this.content.append($('<div>').addClass('busy'));
	}
	else
	{
		this.content.find('.busy').remove();
	}
	return this;
};

/**
 * Show busy overlay while method executes
 * @param {Function} method
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.busyWhile = function(method)
{
	"use strict";

	this.busy(true);
	method();
	return this.busy(false);
};

/**
 * @param {View} shell
 * @param {String} selector
 * @param {Boolean} [barOnTop = false]
 * @this {BaseMediator}
 */
BaseMediator.prototype.init = function(shell, selector, barOnTop)
{
	"use strict";

	this.shell = shell;
	this.view = $(selector);
	this.bar = $('<div>').addClass('content');

	if (this.view.children().length > 0)
	{
		this.view.children().wrapAll('<div class="content">');
	}
	else
	{
		this.view.append(this.bar.clone());
	}
	this.content = this.view.find('> .content');

	var div = $('<div>')
		.addClass('bar')
		.append(this.bar)
		.append($('<div>')
			.addClass('buttons')
			.append($('<button>')
				.attr('title', 'Close')
				.click(this.hide.bind(this))
				.appendIcon('remove', true)
			)
		);

	if (barOnTop)
	{
		this.view.prepend(div.addClass('bar-top'));
	}
	else
	{
		this.view.append(div.addClass('bar-bottom'));
	}
};

/**
 * @param {BaseMediator} other
 * @this {BaseMediator}
 */
BaseMediator.prototype.equals = function(other)
{
	"use strict";

	return this.button == other.button;
};

/**
 * Show the tool and hide any others that are exclusive
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.show = function()
{
	if (this.enabled)
	{
		this.view.show();
		this.visible = true;

		if (this.shell.toolbar) { this.shell.toolbar.select(this.button); }

		this.shell.ensureExclusive(this);
	}
	return this;
};

/**
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.hide = function()
{
	this.view.hide();
	this.visible = false;
	if (this.shell.toolbar) { this.shell.toolbar.deselect(this.button); }
	return this;
};

/**
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.toggle = function()
{
	"use strict";

	return (this.visible) ? this.hide() : this.show();
};

/**
 * Enable tool button
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.enable = function()
{
	"use strict";

	this.enabled = true;
	if (this.shell.toolbar) { this.shell.toolbar.enable(this.button); }
	return this;
};

/**
 * Disable tool button
 * @return {BaseMediator}
 */
BaseMediator.prototype.disable = function()
{
	"use strict";

	this.enabled = false;
	if (this.shell.toolbar) { this.shell.toolbar.disable(this.button); }
	return this;
};

/**
 * @param {Number} [duration]
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.fadeOut = function(duration)
{
	this.content.fadeOut(duration);
	return this;
};

/**
 * @param {Number} [duration]
 * @return {BaseMediator}
 * @this {BaseMediator}
 */
BaseMediator.prototype.fadeIn = function(duration)
{
	this.content.fadeIn(duration);
	return this;
};

/**
 * @param {jQuery} button
 * @param {Boolean} [right = false] Whether to align right, otherwise left
 * @this {BaseMediator}
 */
BaseMediator.prototype.align = function(button, right)
{
	/** @type {Number} */
	var left = button.offset().left;
	/** @constant */
	var border = 2;

	if (right)
	{
		this.view.css('right', (window.innerWidth - (left + button.outerWidth() + border)));
	}
	else
	{
		this.view.css('left', left - border);
	}
};

